<?php

namespace app\admin\controller\user;

use app\common\controller\Backend;
use think\Db;
use Exception;
use think\exception\PDOException;
use think\exception\ValidateException;
use think\Cache;


/**
 * 用户充值
 *
 * @icon fa fa-circle-o
 */
class Recharge extends Backend
{

    /**
     * Recharge模型对象
     * @var \app\admin\model\user\Recharge
     */
    protected $model = null;

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\admin\model\user\Recharge;
        $this->view->assign("typeList", $this->model->getTypeList());
        $this->view->assign("statusList", $this->model->getStatusList());
    }



    /**
     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
     */


    /**
     * 查看
     */
    public function index()
    {
        //当前是否为关联查询
        $this->relationSearch = true;
        //设置过滤方法
        $this->request->filter(['strip_tags', 'trim']);
        if ($this->request->isAjax()) {
            //如果发送的来源是Selectpage，则转发到Selectpage
            if ($this->request->request('keyField')) {
                return $this->selectpage();
            }
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();

            $list = $this->model
                    ->with(['user'])
                    ->where($where)
                    ->order($sort, $order)
                    ->paginate($limit);

            foreach ($list as $row) {
                $row->visible(['id','order_no','money','dou_money','type','status','device_type','notify_num','create_time','pay_time']);
                $row->visible(['user']);
				$row->getRelation('user')->visible(['username']);
            }

            $result = array("total" => $list->total(), "rows" => $list->items());

            return json($result);
        }
        return $this->view->fetch();
    }

    /**
     * 手动回调
     *
     * @return string
     * @throws \think\Exception
     */
    public function notifyXnOrder()
    {
         // 接收传来的参数进行限定条件
         $order_id = input('order_id');
         if(empty($order_id)){
            $this->error("参数有误");
         }
         $user_recharge = DB::name("user_recharge")->where("id",$order_id)->find();
         if($user_recharge['status'] != 1 && $user_recharge['status'] != 3 && $user_recharge['device_type'] != 1){
            $this->error("状态有误");
         }
         try {
            $uri = '/xpay/query_order';
            $appkey = "SgM7386iqymWi0qrj7ReIn7CbgRqLjBA";
            $user_find = DB::name("user")->where("id",$user_recharge['user_id'])->find();
            $data = array(
                "openid" => $user_find['openid'],
                "env" => 0,
                "order_id" => $user_recharge['order_no'],
                "wx_order_id" => "",
            );
            // 
            $post_body = json_encode($data);
            $pay_sig = $this->calc_pay_sig($uri, $post_body, $appkey);
            $access_token = $this->get_access_token();
            $url = 'https://api.weixin.qq.com/xpay/query_order?access_token='.$access_token.'&pay_sig='.$pay_sig;
            $json_res = $this->json_post($url,$data);
            $res = json_decode($json_res,true);
            if($res['errcode'] == '40001'){
                $access_token = $this->get_new_access_token();
                $url = 'https://api.weixin.qq.com/xpay/query_order?access_token='.$access_token.'&pay_sig='.$pay_sig;
                $json_res = $this->json_post($url,$data);
                $res = json_decode($json_res,true);
            }
            if($res['errcode'] != 0){
                $code = 1;
                $msg = $res['errmsg'];
                // DB::name("user_recharge")->where(array("id"=>$user_recharge['id']))->update(array("status"=>3,"back_json"=>$json_res));
            }else{
                $order = $res['order'];
                if($order['status'] != 1 && $order['status'] != 2 && $order['status'] != 3 && $order['status'] != 4){
                    $msg_arr = array(
                        "0" => "订单初始化（未创建成功，不可用于支付）",
                        "1" => "订单创建成功",
                        "2" => "订单已经支付，待发货",
                        "3" => "订单发货中",
                        "4" => "订单已发货",
                        "5" => "订单已经退款",
                        "6" => "订单已经关闭（不可再使用）",
                        "7" => "订单退款失败",
                        "8" => "用户退款完成",
                        "9" => "回收广告金完成",
                        "10" => "分账回退完成",
                    );
                    $code = 1;
                    $msg = $msg_arr[$order['status']];
                    // DB::name("user_recharge")->where(array("id"=>$user_recharge['id']))->update(array("status"=>3,"back_json"=>$json_res));
                }else{
                    if($order['status'] != 1){
                        DB::name("user_recharge")->where("order_no",$user_recharge['order_no'])->update(array("status"=>2,"back_json"=>$json_res,"pay_time"=>date("Y-m-d H:i:s")));
                        $user_find = DB::name("user")->where("id",$user_recharge['user_id'])->find();
                        DB::name("user")->where("id",$user_recharge['user_id'])->setInc("money",$user_recharge['dou_money']);
                        $money_data = array(
                            "user_id" => $user_recharge['user_id'],
                            "money" => $user_recharge['dou_money'],
                            "before" => $user_find['money'],
                            "after" => $user_find['money']+$user_recharge['dou_money'],
                            "memo" => "充值".$user_recharge['money']."元获得".$user_recharge['dou_money']."嘶豆",
                            "createtime" => time()
                        );
                        DB::name("user_money_log")->insert($money_data);
                        
                        $user_recharge_money = DB::name("user_recharge")->where(array("user_id"=>$user_recharge['user_id'],"status"=>2))->sum("money");
                        $pow = pow($user_recharge_money, 1.0/3);
                        $episode_usergood = DB::name("episode_usergood")->where(array("user_id"=>$user_recharge['user_id']))->select();
                        foreach($episode_usergood as $key => $value) {
                            if($value['num'] > 0){
                                $new_num = intval($pow*$value['num']);
                            }elseif($value['num'] < 0){
                                $new_num = intval($pow);
                            }else{
                                $new_num = 0;
                            }
                            DB::name("episode_usergood")->where("id",$value['id'])->update(array("pow_num"=>$new_num));
                        }
                        $system_level = DB::name("system_level")->where("money <=".$user_recharge_money)->order("level desc")->find();
                        if($system_level){
                            DB::name("user")->where("id",$user_recharge['user_id'])->update(array("level"=>$system_level['level']));
                        }
                        
                        if($user_recharge['user_channel_id']){
                            DB::name("user_channel")->where(array("id"=>$user_recharge['user_channel_id']))->setInc("money",$user_recharge['money']);
                            DB::name("user_channel")->where(array("id"=>$user_recharge['user_channel_id']))->setInc("total_money",$user_recharge['money']);
                            DB::name("user_channel")->where(array("id"=>$user_recharge['user_channel_id']))->setInc("today_recharge_num");
                            DB::name("user_channel")->where(array("id"=>$user_recharge['user_channel_id']))->setInc("total_recharge_num");
                        }
                        
                        //trackid有值代表此用户的渠道来源是B站，需要在支付成功以后向B站回传
                        if($user_find['trackid']){
                            $conv_value = bcmul($user_recharge['money'], 100);//转化的价值应该是用户付费的金额
                            $conv_time = $this->getMillisecond();
                            $track_id = $user_find['trackid'];
                            if(!empty($track_id)){
                                //   $track_id = "pbaes.pUNy4MJ2Ys480sM0UwZGtgegI02oMB26nQ0C1alN0X9S2qnwL5ZtrgEPnAOg9rUnS79cXwtXs-PVLkK2Xle3nwMVpDQUH5qSlPSvfSWMLY0WIzFfXB_PODxbOTucGwcDhZ2RhVap89IbWkhFX5xhzfk4alZMf3v8B3733EiwDKAQxekBf6iPPCR0fK3D1aaT";
                                $b_url = "https://cm.bilibili.com/conv/api/conversion/ad/cb/v1?conv_type=USER_COST&conv_time=".$conv_time."&track_id=".$track_id."&conv_value=".$conv_value;
                                file_put_contents("log/notifyOrder_B".date('Ymd').".txt",$b_url.PHP_EOL,FILE_APPEND);
                                $bili_res = file_get_contents($b_url);
                                file_put_contents("log/notifyOrder_B".date('Ymd').".txt",$bili_res.PHP_EOL,FILE_APPEND);
                                file_put_contents("log/notifyOrder_B".date('Ymd').".txt",date('Y-m-d H:i:s').PHP_EOL,FILE_APPEND);


                                //还要回传ORDER_PLACE
                                $b_url = "https://cm.bilibili.com/conv/api/conversion/ad/cb/v1?conv_type=ORDER_PLACE&conv_time=".$conv_time."&track_id=".$track_id."&conv_value=".$conv_value;
                                file_put_contents("log/notifyOrder_B".date('Ymd').".txt",$b_url.PHP_EOL,FILE_APPEND);
                                $bili_res = file_get_contents($b_url);
                                file_put_contents("log/notifyOrder_B".date('Ymd').".txt",$bili_res.PHP_EOL,FILE_APPEND);
                                file_put_contents("log/notifyOrder_B".date('Ymd').".txt",date('Y-m-d H:i:s').PHP_EOL,FILE_APPEND);
                                file_put_contents("log/notifyOrder_B".date('Ymd').".txt","————————————————————————————————————————————————————————————————————".PHP_EOL,FILE_APPEND);
                            }
                        }

                        //tencentid有值代表此用户的渠道来源是腾讯广告，需要在支付成功以后向腾讯回传
                        if($user_find['tencentid']){
                            //要向callback的地址提交一个post请求,先拿到callback地址,然后urldecode一下,最后上报注册信息
                            $post_url = DB::name("cpa_teng_xun")->where('id','=',$user_find['tencentid'])->value('callback');
                            $post_url = urldecode($post_url);
                            $post_data['actions'] = [];
                            $post_data['actions'][0]['action_type'] = "PURCHASE";
                            $post_data['actions'][0]['action_time'] = time();
                            $post_data['actions'][0]['user_id']['wechat_app_id'] = $this->AppId;
                            $post_data['actions'][0]['user_id']['wechat_openid'] = $user_find['openid'];
                            $post_data['actions'][0]['action_param']['value'] = $user_recharge['money'];

                            file_put_contents("log/notifyOrder_gdt".date('Ymd').".txt",$post_url.PHP_EOL,FILE_APPEND);
                            file_put_contents("log/notifyOrder_gdt".date('Ymd').".txt",json_encode($post_data,JSON_UNESCAPED_UNICODE).PHP_EOL,FILE_APPEND);
                            $post_res = $this->json_post($post_url,$post_data);
                            file_put_contents("log/notifyOrder_gdt".date('Ymd').".txt",$post_res.PHP_EOL,FILE_APPEND);
                            file_put_contents("log/notifyOrder_gdt".date('Ymd').".txt",date('Y-m-d H:i:s').PHP_EOL,FILE_APPEND);
                            file_put_contents("log/notifyOrder_gdt".date('Ymd').".txt","————————————————————————————————————————————————————————————————————".PHP_EOL,FILE_APPEND);
                        }

                        //clickid有值代表此用户的渠道来源是抖音，需要在支付成功以后向抖音回传
                        if($user_find['clickid']){
                            file_put_contents("log/notifyOrder_dy".date('Ymd').".txt","clickid=".$user_find['clickid'].PHP_EOL,FILE_APPEND);

                            $d_url = "https://ad.oceanengine.com/track/activate/?callback={$user_find['clickid']}&event_type=2";

                            $props = [];

                            $props['pay_amount'] = bcmul($user_recharge['money'], 100);//转化的价值应该是用户付费的金额
                            $props = json_encode($props);

                            $d_url .= "&props=".urlencode($props);
                            file_put_contents("log/notifyOrder_dy".date('Ymd').".txt",$d_url.PHP_EOL,FILE_APPEND);
                            $dy_res = file_get_contents($d_url);
                            file_put_contents("log/notifyOrder_dy".date('Ymd').".txt",$dy_res.PHP_EOL,FILE_APPEND);
                            file_put_contents("log/notifyOrder_dy".date('Ymd').".txt",date('Y-m-d H:i:s').PHP_EOL,FILE_APPEND);
                            file_put_contents("log/notifyOrder_dy".date('Ymd').".txt","————————————————————————————————————————————————————————————————————".PHP_EOL,FILE_APPEND);


                            $notify_order_dy_insert_data = [];
                            $notify_order_dy_insert_data['user_id'] = $user_find['id'];
                            $notify_order_dy_insert_data['clickid'] = $user_find['clickid'];
                            $notify_order_dy_insert_data['url'] = $d_url;
                            $notify_order_dy_insert_data['money'] = $user_recharge['money'];
                            $notify_order_dy_insert_data['back_json'] = $dy_res;
                            $notify_order_dy_insert_data['createtime'] = date('Y-m-d H:i:s');

                            DB::name("notify_order_dy")->insert($notify_order_dy_insert_data);

                        }

                        //如果有clue_token字段，则表示用户是字节的巨量来源的，付款时要回传数据
                        if($user_find['clue_token']){
                            $post_url = "https://clue.oceanengine.com/outer/wechat/applet/token/1794573964023881";

                            $token = "DA4F57B4A91927287BDB4C22CA1D9817";
                            $nonce = rand(10000,99999);//随机整数，防止请求被中间劫持篡改
                            $timestamp = time();//当前时间戳

                            $collect = [
                                (string)$token,(string)$nonce,(string)$timestamp,
                            ];

                            usort($collect,'strcmp');
                            $signature = sha1(implode('',$collect));

                            $post_url .= "?timestamp={$timestamp}&nonce={$nonce}&signature={$signature}";
                            file_put_contents("log/notifyOrder_zj".date('Ymd').".txt",$post_url.PHP_EOL,FILE_APPEND);


                            $post_data = [];
                            $post_data['clue_token'] = (string)$user_find['clue_token'];
                            $post_data['open_id'] = (string)$user_find['openid'];
                            $post_data['event_type'] = "2";//2-付费
                            $post_data['props']['pay_amount'] = (int)bcmul($user_recharge['money'], 100);
                            $post_res = $this->json_post($post_url,$post_data);
                            file_put_contents("log/notifyOrder_zj".date('Ymd').".txt",json_encode($post_data,JSON_UNESCAPED_UNICODE).PHP_EOL,FILE_APPEND);
                            file_put_contents("log/notifyOrder_zj".date('Ymd').".txt",json_encode($post_res,JSON_UNESCAPED_UNICODE).PHP_EOL,FILE_APPEND);
                            file_put_contents("log/notifyOrder_zj".date('Ymd').".txt",date('Y-m-d H:i:s').PHP_EOL,FILE_APPEND);
                            file_put_contents("log/notifyOrder_zj".date('Ymd').".txt","————————————————————————————————————————————————————————————————————".PHP_EOL,FILE_APPEND);



                            $notify_order_zj_insert_data = [];
                            $notify_order_zj_insert_data['user_id'] = $user_find['id'];
                            $notify_order_zj_insert_data['clue_token'] = $user_find['clue_token'];
                            $notify_order_zj_insert_data['url'] = $post_url;
                            $notify_order_zj_insert_data['money'] = $user_recharge['money'];
                            $notify_order_zj_insert_data['back_json'] = json_encode($post_res,JSON_UNESCAPED_UNICODE);
                            $notify_order_zj_insert_data['createtime'] = date('Y-m-d H:i:s');

                            DB::name("notify_order_zj")->insert($notify_order_zj_insert_data);


                        }
                        
                        //扣除虚拟支付的余额
                        $uri = '/xpay/currency_pay';
                        $data = array(
                            "openid" => $user_find['openid'],
                            "env" => 0,
                            "user_ip" => $_SERVER['REMOTE_ADDR'],
                            "amount" => ceil($user_recharge['money']*100),
                            "order_id" => $user_recharge['order_no'],
                            "payitem" => "testpayitem",
                            "remark" => "testremark",
                            "device_type" => 1,
                        );
                        // 
                        $post_body = json_encode($data);
                        $pay_sig = $this->calc_pay_sig($uri, $post_body, $appkey);
                        $access_token = $this->get_access_token();
                        $signature = $this->calc_signature($post_body, $user_find['session_key']);
                        // print_r($access_token);exit;
                        $url = 'https://api.weixin.qq.com/xpay/currency_pay?access_token='.$access_token.'&pay_sig='.$pay_sig.'&signature='.$signature;
                        $res = json_decode($this->json_post($url,$data),true);
                        file_put_contents("testW1111.txt",var_export($res,true),FILE_APPEND);
                    }
                    $code = 2;
                    $msg = "成功";
                }
            }
            DB::name("user_recharge")->where(array("id"=>$user_recharge['id']))->setInc("notify_num");
        } catch (Exception $e) {
            $code = 1;
            $msg = "失败";
        }
        if($code == 1){
            $this->error($msg);
        }else{
            $this->success($msg);
        }
    }

    function calc_pay_sig($uri, $post_body, $appkey) {
        // pay_sig签名算法
        $need_sign_msg = $uri . '&' . $post_body;
        $pay_sig = hash_hmac('sha256', $need_sign_msg, $appkey);
        return $pay_sig;
    }
    function calc_signature($post_body, $session_key) {
        // 用户登录态signature签名算法
        $need_sign_msg = $post_body;
        $signature = hash_hmac('sha256', $need_sign_msg, $session_key);
        return $signature;
    }
    
    //获取小程序二维码的token
    public function get_access_token()
    {
        //先判断缓存里面的access_token过期了没有
        if(Cache::get('access_token')){
            //没过期直接拿出来用
            $a = Cache::get('access_token');
            return $a;
        }else{
            //过期了就重新获取
            $appid = 'wxbae1b3248b60e1d8';
            $secret = 'b3df3f25537d5c1cdd9ac67e47b7391c';
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appid&secret=$secret";
            
            //请求接口，获取accesstoken
            $user_obj = $this->curlHttp($url);
            //然后将accesstoken存入缓存里面，官方过期时间7200秒，缓存里面可以过期的早一点，自己把控
            Cache::set('access_token',$user_obj['access_token'],900);

            return Cache::get('access_token');
        }
    }

    //获取小程序最新二维码的token
    public function get_new_access_token()
    {
        //过期了就重新获取
        $appid = 'wxbae1b3248b60e1d8';
        $secret = 'b3df3f25537d5c1cdd9ac67e47b7391c';
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appid&secret=$secret";
        
        //请求接口，获取accesstoken
        $user_obj = $this->curlHttp($url);
        //然后将accesstoken存入缓存里面，官方过期时间7200秒，缓存里面可以过期的早一点，自己把控
        Cache::set('access_token',$user_obj['access_token'],900);

        return Cache::get('access_token');
    }

     /**
     * 发送post请求
     */
    function json_post($url, $data = [])
    {
        //$data=http_build_query($data);
        //$data=json_encode($data);
        $curl = curl_init();

        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        if(!$data){
            return 'data is null';
        }
        if(is_array($data))
        {
            $data = json_encode($data);
        }
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_HTTPHEADER,array(
            'Content-Type: application/json; charset=utf-8',
            'Content-Length:' . strlen($data),
            'Cache-Control: no-cache',
            'Pragma: no-cache'
        ));
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $res = curl_exec($curl);
        $errorno = curl_errno($curl);
        if ($errorno) {
            return $errorno;
        }
        curl_close($curl);
        return $res;

    }

    function curlHttp($url)
    {

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $output = curl_exec($ch);
        //释放curl句柄
        curl_close($ch);
        return json_decode($output, true);
    }


}
